package io.hellsinger.navigation.proccessor.screen

import com.google.devtools.ksp.processing.CodeGenerator
import com.google.devtools.ksp.processing.Dependencies
import com.google.devtools.ksp.processing.KSPLogger
import com.google.devtools.ksp.processing.Resolver
import com.google.devtools.ksp.processing.SymbolProcessor
import com.google.devtools.ksp.symbol.ClassKind
import com.google.devtools.ksp.symbol.KSAnnotated
import com.google.devtools.ksp.symbol.KSClassDeclaration
import com.google.devtools.ksp.symbol.KSVisitorVoid
import com.google.devtools.ksp.validate
import java.io.OutputStream

class NavScreenControllerProcessor(
    private val generator: CodeGenerator,
    private val logger: KSPLogger,
) : SymbolProcessor {
    operator fun OutputStream.plusAssign(content: String) = write(content.toByteArray())

    override fun process(resolver: Resolver): List<KSAnnotated> {
        val symbols =
            resolver
                .getSymbolsWithAnnotation(annotationName = NavigationScreenControllerRoute::name.toString())
                .filterIsInstance<KSClassDeclaration>()
        if (!symbols.iterator().hasNext()) return emptyList()

        val file =
            generator.createNewFile(
                dependencies = Dependencies(false, *resolver.getAllFiles().toList().toTypedArray()),
                packageName = "io.hellsinger.navigation.processor.screen",
                fileName = "GeneratedRoutes",
            )
        file += "io.hellsinger.navigation.processor.screen\n"
        symbols.forEach { it.accept(Visitor(file), Unit) }
        file.close()

        val unableToProcess = symbols.filterNot { it.validate() }.toList()
        return unableToProcess
    }

    inner class Visitor(
        private val file: OutputStream,
    ) : KSVisitorVoid() {
        override fun visitClassDeclaration(
            classDeclaration: KSClassDeclaration,
            data: Unit,
        ) {
            if (classDeclaration.classKind != ClassKind.CLASS) {
                logger.error("Only class implementation can be annotated")
                return
            }
            val annotation =
                classDeclaration.annotations.first {
                    it.shortName.asString() ==
                        NavigationScreenControllerRoute::name.toString()
                }
            val route = annotation.arguments[0].value as String
        }
    }
}
